/*******************************************************************************
* Copyright (c) 2009, 2011 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.obeonetwork.dsl.uml2.design.api.services;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.ui.EMFEditUIPlugin;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.pde.internal.ui.PDEPlugin;
import org.eclipse.pde.internal.ui.wizards.ResizableWizardDialog;
import org.eclipse.pde.internal.ui.wizards.exports.PluginExportWizard;
import org.eclipse.sirius.business.api.session.Session;
import org.eclipse.sirius.business.api.session.SessionManager;
import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.viewpoint.DSemanticDecorator;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWizard;
import org.eclipse.ui.PlatformUI;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.Extension;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.PackageableElement;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.resource.UMLResource;
import org.obeonetwork.dsl.uml2.design.internal.dialogs.ExtraAssociationSelectionDialog;
import org.obeonetwork.dsl.uml2.design.internal.dialogs.ImportMetaclassDialog;
import org.obeonetwork.dsl.uml2.design.internal.dialogs.InitProfilePluginDialog;
import org.obeonetwork.dsl.uml2.design.internal.services.AssociationServices;
import org.obeonetwork.dsl.uml2.design.internal.services.EcoreToGenmodel;
import org.obeonetwork.dsl.uml2.design.internal.services.ElementServices;
import org.obeonetwork.dsl.uml2.design.internal.services.ExtensionServices;
import org.obeonetwork.dsl.uml2.design.internal.services.GenerateModelCode;
import org.obeonetwork.dsl.uml2.design.internal.services.GenericUMLProfileTools;
import org.obeonetwork.dsl.uml2.design.internal.services.LabelServices;
import org.obeonetwork.dsl.uml2.design.internal.services.LogServices;
import org.obeonetwork.dsl.uml2.design.internal.services.NewPluginProject;
import org.obeonetwork.dsl.uml2.design.internal.services.NodeInverseRefsServices;
import org.obeonetwork.dsl.uml2.design.internal.services.ProfileServices;
import org.obeonetwork.dsl.uml2.design.internal.services.UmlToEcore;
import org.obeonetwork.dsl.uml2.design.internal.services.ValidateEmfElement;
import org.obeonetwork.dsl.uml2.design.internal.services.ValidateUMLElement;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
/**
* A set of services to handle the Package containment diagram.
*
* @author Mohamed-Lamine BOUKHANOUFA <a href="mailto:mohamed-lamine.boukhanoufa@obeo.fr" >mohamed-lamine.
* boukhanoufa@obeo.fr</a>
* @author Melanie Bats <a href="mailto:melanie.bats@obeo.fr">melanie.bats@obeo.fr</a>
*/
@SuppressWarnings("restriction")
public class ProfileDiagramServices extends AbstractDiagramServices {
private static final String YES = "Yes"; //$NON-NLS-1$
private static final String NO = "No"; //$NON-NLS-1$
private static final String OK = "OK"; //$NON-NLS-1$
private static final String UNDEFINE_PROFILE = "Undefine the Profile"; //$NON-NLS-1$
private static final String OBEO_NETWORK_PLUGIN_NAME = new String("org.obeonetwork"); //$NON-NLS-1$
private static final String OBEO_NETWORK_URI = new String("http://www.obeonetwork.org/"); //$NON-NLS-1$
private String profileName = new String();
private static final String DEFAULT_PROFILE_NAME = new String("profile"); //$NON-NLS-1$
private String profilePluginName = new String();
private String rootProfileURI = new String();
private static final String SEPARATOR = new String("/"); //$NON-NLS-1$
private static final String NS_URI = new String("nsURI"); //$NON-NLS-1$
private static final String EXTENSION = new String("extension"); //$NON-NLS-1$
private static final String POINT = new String("point"); //$NON-NLS-1$
private static final String PLATFORM_PLUGIN = new String("platform:/plugin"); //$NON-NLS-1$
/**
* Add to the plug-in the extension for the profile.
*
* @param profilePlugin
* the plug-in
* @param modelFolder
* the folder of the profile
* @param profileCopy
* the profile
*/
private void addProfileExtensions(final IProject profilePlugin, final IFolder modelFolder,
final Profile profileCopy) {
final String exceptionMsg = "addProfileExtensions(" //$NON-NLS-1$
+ profilePlugin.getClass() + "," + modelFolder.getClass() + "," //$NON-NLS-1$ //$NON-NLS-2$
+ profileCopy.getClass() + ") not handled"; //$NON-NLS-1$
final IFile pluginXML = profilePlugin.getFile("plugin.xml"); //$NON-NLS-1$
final DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = builderFactory.newDocumentBuilder();
} catch (final ParserConfigurationException e) {
LogServices.INSTANCE.error(exceptionMsg, e);
}
org.w3c.dom.Document document = null;
try {
if (builder != null) {
document = builder.parse(pluginXML.getLocation().toFile());
}
} catch (final SAXException e) {
LogServices.INSTANCE.error(exceptionMsg, e);
} catch (final IOException e) {
LogServices.INSTANCE.error(exceptionMsg, e);
} catch (final Exception e) {
throw new RuntimeException(e);
}
if (document != null) {
final String xmiIdProfileCopy = profileCopy.eResource().getURIFragment(profileCopy);
final Node racine = document.getDocumentElement();
org.w3c.dom.Element extensionForGeneratedPackage = document.createElement(EXTENSION);
extensionForGeneratedPackage.setAttribute(POINT, "org.eclipse.uml2.uml.generated_package"); //$NON-NLS-1$
org.w3c.dom.Element profile = document.createElement(DEFAULT_PROFILE_NAME);
profile.setAttribute("location", PLATFORM_PLUGIN //$NON-NLS-1$
+ profileCopy.eResource().getURI() + "#" + xmiIdProfileCopy); //$NON-NLS-1$
profile.setAttribute("uri", profileCopy.getURI()); //$NON-NLS-1$
extensionForGeneratedPackage.appendChild(profile);
racine.appendChild(extensionForGeneratedPackage);
final EList<Element> allOwnedElements = profileCopy.allOwnedElements();
for (final Element ownedPackageElement : allOwnedElements) {
if (ownedPackageElement instanceof Profile) {
final Profile ownedProfile = (Profile)ownedPackageElement;
final String xmiIdownedPackage = ownedProfile.eResource().getURIFragment(ownedProfile);
extensionForGeneratedPackage = document.createElement(EXTENSION);
extensionForGeneratedPackage.setAttribute(POINT,
"org.eclipse.uml2.uml.generated_package"); //$NON-NLS-1$
profile = document.createElement(DEFAULT_PROFILE_NAME);
profile.setAttribute("location", //$NON-NLS-1$
PLATFORM_PLUGIN + ownedProfile.eResource().getURI() + "#" //$NON-NLS-1$
+ xmiIdownedPackage);
profile.setAttribute("uri", ownedProfile.getURI()); //$NON-NLS-1$
extensionForGeneratedPackage.appendChild(profile);
racine.appendChild(extensionForGeneratedPackage);
}
}
final org.w3c.dom.Element extensionForUriMapping = document.createElement(EXTENSION);
extensionForUriMapping.setAttribute(POINT, "org.eclipse.emf.ecore.uri_mapping"); //$NON-NLS-1$
final org.w3c.dom.Element mapping = document.createElement("mapping"); //$NON-NLS-1$
mapping.setAttribute("source", "pathmap://MY_PROFILES/"); //$NON-NLS-1$ //$NON-NLS-2$
mapping.setAttribute("target", //$NON-NLS-1$
PLATFORM_PLUGIN + modelFolder.getFullPath());
extensionForUriMapping.appendChild(mapping);
racine.appendChild(extensionForUriMapping);
// serialise the document to an xml file.
Transformer transformer = null;
try {
transformer = TransformerFactory.newInstance().newTransformer();
} catch (final TransformerConfigurationException e) {
LogServices.INSTANCE.error(exceptionMsg, e);
} catch (final TransformerFactoryConfigurationError e) {
LogServices.INSTANCE.error(exceptionMsg, e);
}
final Result output = new StreamResult(pluginXML.getLocation().toFile());
final Source input = new DOMSource(document);
try {
if (transformer != null) {
transformer.transform(input, output);
}
} catch (final TransformerException e) {
LogServices.INSTANCE.error(exceptionMsg, e);
}
}
}
/**
* Can create extension.
*
* @param source
* Source
* @param target
* Target
* @return True if extension can be created between source and target
*/
public boolean canCreateExtension(final Stereotype source, final ElementImport target) {
return ExtensionServices.INSTANCE.canCreateExtension(source, target);
}
/**
* Can create extension.
*
* @param source
* Source
* @param target
* Target
* @return True if extension can be created between source and target
*/
public boolean canCreateExtension(final Stereotype source, final Stereotype target) {
return ExtensionServices.INSTANCE.canCreateExtension(source, target);
}
/**
* Test if is possible to drop an ElementImport from an old profile to a new profile.
*
* @param elementImport
* @param oldProfile
* @param newProfile
* @return true if is possible to drop, else false.
*/
private boolean canDropElementImport(final ElementImport elementImport, final Profile oldProfile,
final Profile newProfile) {
if (newProfile.getImportedMember(elementImport.getImportedElement().getName()) != null) {
return false;
}
for (final Extension extension : oldProfile.getOwnedExtensions(false)) {
if (extension.getMetaclass() != null
&& extension.getMetaclass().equals(elementImport.getImportedElement())) {
return false;
}
}
return true;
}
/**
* Compute element import label.
*
* @param element
* Element import
* @return Label
*/
public String computeElementImportLabel(ElementImport element) {
return LabelServices.INSTANCE.computeElementImportLabel(element);
}
/**
* Compute profile label.
*
* @param element
* Profile
* @return Label
*/
public String computeProfileLabel(Profile element) {
return LabelServices.INSTANCE.computeProfileLabel(element);
}
/**
* Compute the source label of for the Extra association defined by the stereotype "stereotype".
*
* @param stereotype
* the stereotype
* @return the label
*/
public String computeSourceLabel(final Stereotype stereotype) {
final ArrayList<Property> properties = ProfileServices.INSTANCE
.getRelationShipSourceTargetPeroperties(getMetaclass(stereotype.getOwnedAttributes().get(0)));
return LabelServices.INSTANCE.computeAssociationEndLabel(properties.get(0));
}
/**
* Compute the label of the given stereotype.
*
* @param element
* the {@link Stereotype} for which to retrieve a label.
* @return the computed label.
*/
public String computeStereotypeLabel(Stereotype element) {
return LabelServices.INSTANCE.computeStereotypeLabel(element);
}
/**
* Compute the target label of for the Extra association defined by the stereotype "stereotype".
*
* @param stereotype
* the stereotype
* @return the label
*/
public String computeTargetLabel(final Stereotype stereotype) {
final ArrayList<Property> properties = ProfileServices.INSTANCE
.getRelationShipSourceTargetPeroperties(getMetaclass(stereotype.getOwnedAttributes().get(0)));
return LabelServices.INSTANCE.computeAssociationEndLabel(properties.get(1));
}
/**
* compute the uri of element.
*
* @param element
* for which the uri will be computed
* @return the uri
*/
private String computeURI(final NamedElement element) {
String uri = null;
if (element.getOwner() == null && element.getNearestPackage().getURI() != null
&& element.getNearestPackage().getURI().length() != 0) {
uri = element.getNearestPackage().getURI();
} else if (element.getOwner() != null && element.getOwner().getNearestPackage() != null
&& element.getOwner().getNearestPackage().getURI() != null) {
uri = element.getOwner().getNearestPackage().getURI() + element.getName() + SEPARATOR;
} else {
uri = rootProfileURI;
}
return uri;
}
/**
* Create an UML Association between the stereotypes source and target.
*
* @param stereotypeSource
* stereotype source.
* @param stereotypeTarget
* stereotype target.
* @return the created association.
*/
public Association createAssociation(final Stereotype stereotypeSource,
final Stereotype stereotypeTarget) {
return createAssociation(stereotypeSource, stereotypeTarget, stereotypeSource.getName() + "To" //$NON-NLS-1$
+ stereotypeTarget.getName());
}
/**
* Create an UML Association between the stereotypes source and target.
*
* @param stereotypeSource
* stereotype source.
* @param stereotypeTarget
* stereotype target.
* @param associationName
* the name of the Association.
* @return the created association.
*/
private Association createAssociation(final Stereotype stereotypeSource,
final Stereotype stereotypeTarget, final String associationName) {
final Association association = UMLFactory.eINSTANCE.createAssociation();
// The name is provided by the item provider
final Property sourceStereoProperty = UMLFactory.eINSTANCE.createProperty();
sourceStereoProperty.setName(stereotypeSource.getName() + "s"); //$NON-NLS-1$
sourceStereoProperty.setType(stereotypeSource);
sourceStereoProperty.setLower(0);
sourceStereoProperty.setUpper(-1);
association.getOwnedEnds().add(sourceStereoProperty);
final Property targetStereoProperty = UMLFactory.eINSTANCE.createProperty();
targetStereoProperty.setName(stereotypeTarget.getName() + "s"); //$NON-NLS-1$
targetStereoProperty.setType(stereotypeTarget);
targetStereoProperty.setLower(0);
targetStereoProperty.setUpper(-1);
association.getOwnedEnds().add(targetStereoProperty);
association.getNavigableOwnedEnds().add(targetStereoProperty);
stereotypeSource.getProfile().getPackagedElements().add(association);
return association;
}
/**
* Create an UML Extension between the stereotype source and the target element.
*
* @param stereotype
* source.
* @param targetElement
* the target.
*/
public void createExtension(final Stereotype stereotype, final Element targetElement) {
ExtensionServices.INSTANCE.createExtension(stereotype, targetElement);
}
/**
* Create an extra association between the stereotype source 'stereotypeSource' and the the stereotype
* target 'stereotypeTarget'. the result stereotype is named 'stereotypName'.
*
* @param stereotypeSource
* the stereotype source.
* @param stereotypeTarget
* the stereotype target.
* @param stereotypName
* the stereotype name.
* @param result
* the metaclass selected for of the creation of the extra association.
* @param profile
* owner of the stereotypes.
* @return the new stereotype of the extra association.
*/
private Stereotype createExtraAssociation(final Stereotype stereotypeSource,
final Stereotype stereotypeTarget, final String stereotypName, final Object[] result,
final Profile profile) {
ElementImport metaClass = null;
Stereotype newStereotype = null;
if (result != null && result[0] instanceof Class) {
final Class selectedMetaclass = (Class)result[0];
final PackageableElement importedMember = profile.getImportedMember(selectedMetaclass.getName());
if (importedMember == null) {
metaClass = profile.createMetaclassReference(selectedMetaclass);
} else {
metaClass = profile.getElementImport(importedMember);
}
}
if (metaClass != null) {
newStereotype = UMLFactory.eINSTANCE.createStereotype();
newStereotype.setName(stereotypName);
profile.getOwnedStereotypes().add(newStereotype);
ExtensionServices.INSTANCE.createMetaclassExtension(newStereotype, metaClass);
createStereotypeAssociation(newStereotype, metaClass, stereotypeSource, stereotypeTarget);
}
return newStereotype;
}
/**
* A message dialog for the creation of an extra association between the stereotype source
* 'stereotypeSource' and the the stereotype target 'targetElement'.
*
* @param stereotypeSource
* stereotype source.
* @param targetElement
* stereotype target.
* @param profile
* owner of the stereotypes.
*/
public void createExtraAssociationDialog(final Stereotype stereotypeSource, final Element targetElement,
final Profile profile) {
final ExtraAssociationSelectionDialog dialog = new ExtraAssociationSelectionDialog(
PlatformUI.getWorkbench().getDisplay().getActiveShell(), profile, stereotypeSource,
targetElement, false);
dialog.open();
if (dialog.getResult() != null) {
if (targetElement instanceof Stereotype) {
final Stereotype stereotypeTarget = (Stereotype)targetElement;
createExtraAssociation(stereotypeSource, stereotypeTarget, dialog.getAssociationName(),
dialog.getResult(), profile);
}
}
}
/**
* Create a new plug-in project with progress bar. see {@link createPluginProject}
*
* @param pluginName
* @return
*/
private IProject createPluginProjectWithProgress(final String pluginName) {
final Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
final NewPluginProject newPluginProject = new NewPluginProject();
final IProject[] profilePlugin = new IProject[1];
final IRunnableWithProgress validationRunnable = new IRunnableWithProgress() {
public void run(final IProgressMonitor progressMonitor)
throws InvocationTargetException, InterruptedException {
try {
profilePlugin[0] = newPluginProject.createPluginProject(pluginName,
new ArrayList<String>(Arrays.asList("src")), //$NON-NLS-1$
new ArrayList<IProject>(), new HashSet<String>(),
new ArrayList<String>(Arrays.asList("org.eclipse.ui", //$NON-NLS-1$
"org.eclipse.core.runtime")), //$NON-NLS-1$
new NullProgressMonitor(), shell);
} finally {
progressMonitor.done();
}
}
};
try {
new ProgressMonitorDialog(shell).run(true, true, validationRunnable);
} catch (final Exception exception) {
EMFEditUIPlugin.INSTANCE.log(exception);
}
return profilePlugin[0];
}
/**
* Create a new {@link Stereotype} in the profile that directly or indirectly contains the elementImport
* in parameter and create a extension to this elementImport from the new created stereotype.
*
* @param elementImport
* the elementImport.
* @return a new stereotype.
*/
public Stereotype createStereotype(ElementImport elementImport) {
final Stereotype newStereotype = UMLFactory.eINSTANCE.createStereotype();
ExtensionServices.INSTANCE.getProfileOwner(elementImport).getOwnedStereotypes().add(newStereotype);
ExtensionServices.INSTANCE.createMetaclassExtension(newStereotype, elementImport);
return newStereotype;
}
/**
* Create a new {@link Stereotype} in the profile that directly or indirectly contains the package_ in
* parameter.
*
* @param package_
* the package_.
* @return a new stereotype.
*/
public Stereotype createStereotype(Package package_) {
final Stereotype newStereotype = UMLFactory.eINSTANCE.createStereotype();
package_.getOwnedStereotypes().add(newStereotype);
return newStereotype;
}
/**
* Create a new {@link Stereotype} in the profile.
*
* @param profile
* the profile.
* @return a new stereotype.
*/
public Stereotype createStereotype(Profile profile) {
final Stereotype newStereotype = UMLFactory.eINSTANCE.createStereotype();
profile.getOwnedStereotypes().add(newStereotype);
return newStereotype;
}
/**
* Create a new {@link Stereotype} in the profile that directly or indirectly contains the stereotype in
* parameter and create a generalization to this stereotype from the new created stereotype.
*
* @param stereotype
* the stereotype.
* @return a new stereotype.
*/
public Stereotype createStereotype(Stereotype stereotype) {
final Stereotype newStereotype = UMLFactory.eINSTANCE.createStereotype();
if (stereotype.getOwner() instanceof Package) {
((Package)stereotype.getOwner()).getOwnedStereotypes().add(newStereotype);
}
ExtensionServices.INSTANCE.createGeneralization(newStereotype, stereotype);
return newStereotype;
}
/**
* Create an StereotypeAssociation for the extra Association.
*
* @param stereotype
* of the extra Association
* @param elementImport
* of the extra Association
* @param stereotypeSource
* of the extra Association
* @param stereotypeTarget
* of the extra Association
*/
private void createStereotypeAssociation(final Stereotype stereotype, final ElementImport elementImport,
final Stereotype stereotypeSource, final Stereotype stereotypeTarget) {
final PackageableElement importedElement = elementImport.getImportedElement();
if (importedElement != null && importedElement instanceof Type
&& ExtensionServices.INSTANCE.isExtendedBy((Type)importedElement, stereotype)) {
final Type metaclass = (Type)importedElement;
final Class metaclassClass = (Class)importedElement;
final ArrayList<Property> properties = ProfileServices.INSTANCE
.getRelationShipSourceTargetPeroperties(metaclassClass);
final Property sourceProperty = properties.get(0);
final Property targetProperty = properties.get(1);
metaclassClass.getAttributes();
final Property associationSourceEnd = UMLFactory.eINSTANCE.createProperty();
associationSourceEnd.setName("sourceRole_" + sourceProperty.getName()); //$NON-NLS-1$
associationSourceEnd.setType(stereotypeSource);
stereotype.getOwnedAttributes().add(associationSourceEnd);
final Property associationTargetEnd = UMLFactory.eINSTANCE.createProperty();
associationTargetEnd.setName("targetRole_" + targetProperty.getName()); //$NON-NLS-1$
associationTargetEnd.setType(stereotypeTarget);
stereotype.getOwnedAttributes().add(associationTargetEnd);
final Extension extension = ExtensionServices.INSTANCE.getExtension(stereotype, metaclass);
extension.getMemberEnds().add(associationSourceEnd);
extension.getMemberEnds().add(associationTargetEnd);
}
}
/**
* Dialog message to define a profile.
*
* @param rootProfile
* to define
*/
public void defineProfileDialog(final Profile rootProfile) {
defineProfileDialog(rootProfile, ProfileServices.INSTANCE.getAllSubProfiles(rootProfile));
}
/**
* Dialog message to define a profile.
*
* @param rootProfile
* to define
* @param allContentProfile
* to define
*/
private void defineProfileDialog(final Profile rootProfile, final List<Profile> allContentProfile) {
boolean result = false;
final String[] buttonYes = {OK};
final Shell activeShell = PlatformUI.getWorkbench().getDisplay().getActiveShell();
MessageDialog msgDialogYes = null;
result = ProfileServices.INSTANCE.defineProfile(rootProfile, allContentProfile);
if (result) {
msgDialogYes = new MessageDialog(activeShell, "Define the Profile", null, //$NON-NLS-1$
"The profile is defined", MessageDialog.INFORMATION, buttonYes, 0); //$NON-NLS-1$
msgDialogYes.open();
}
}
/**
* deleteElementImport delete an elementImport and all its references (base_ attributes of the
* stereotypes).
*
* @param elementImport
* to delete.
* @param profile
* owner of element import.
*/
private void deleteElementImport(final ElementImport elementImport, final Profile profile) {
for (final Extension extension : profile.getOwnedExtensions(false)) {
if (extension.getMetaclass() != null
&& extension.getMetaclass().equals(elementImport.getImportedElement())) {
deleteExtension(extension, profile);
}
}
EcoreUtil.delete(elementImport, true);
}
/**
* deleteExtension delete an extension and all its references (base_ attributes of the stereotype).
*
* @param extension
* to delete.
* @param profile
* owner of extension.
*/
private void deleteExtension(final Extension extension, final Profile profile) {
for (final Element relatedElement : extension.getRelatedElements()) {
if (relatedElement instanceof Stereotype && extension.getMetaclass() != null) {
final EList<Property> properties = ((Stereotype)relatedElement).getAttributes();
int propertiesSize = properties.size();
for (int i = 0; i < propertiesSize; i++) {
if (properties.get(i).getAssociation() != null
&& properties.get(i).getAssociation().equals(extension)) {
properties.get(i).destroy();
i--;
propertiesSize--;
}
}
}
}
EcoreUtil.delete(extension, true);
}
/**
* deleteStereotype delete an stereotype and all its references (Extensions, Generalizations).
*
* @param stereotype
* to delete.
* @param profile
* owner of stereotype.
*/
private void deleteStereotype(final Stereotype stereotype, final Profile profile) {
for (final Extension extension : profile.getOwnedExtensions(false)) {
if (extension.getEndType(stereotype.getName()) != null) {
final Property baseProperty = extension.getMemberEnd("base_" //$NON-NLS-1$
+ extension.getMetaclass().getName(), extension.getMetaclass());
if (baseProperty != null && baseProperty.getOwner().equals(stereotype)) {
EcoreUtil.delete(extension, true);
}
}
}
EcoreUtil.delete(stereotype, true);
}
/**
* deleteUMLElment delete an UML element and all its references.
*
* @param element
* to delete.
* @param profile
* owner of element.
*/
public void deleteUMLElement(final Element element, final Profile profile) {
if (element instanceof ElementImport) {
deleteElementImport((ElementImport)element, profile);
} else if (element instanceof Stereotype) {
deleteStereotype((Stereotype)element, profile);
} else if (element instanceof Extension) {
deleteExtension((Extension)element, profile);
} else {
EcoreUtil.delete(element, true);
}
}
/**
* Delete an UML Package.
*
* @param package_
* the package
*/
public void deleteUMLPackage(final Package package_) {
EcoreUtil.delete(package_, true);
}
/**
* Drop from diagram.
*
* @param newContainer
* Container
* @param semanticElement
* Semantic element
* @param containerView
* Container view
*/
public void dropFromDiagramProfileService(final Element newContainer, final Element semanticElement,
final DSemanticDecorator containerView) {
final Session session = SessionManager.INSTANCE.getSession(newContainer);
boolean doTheDrop = true;
final Element oldContainer = semanticElement.getOwner();
final TransactionalEditingDomain domain = session.getTransactionalEditingDomain();
Command cmd = null;
if (newContainer instanceof Profile && oldContainer instanceof Profile
&& newContainer != oldContainer) {
final Profile newProfile = (Profile)newContainer;
final Profile oldProfile = (Profile)oldContainer;
// Add the ElementImport to 'MetaclassReference' of newContainer
// (profile)
if (semanticElement instanceof ElementImport) {
final ElementImport elementImport = (ElementImport)semanticElement;
if (canDropElementImport(elementImport, oldProfile, newProfile)) {
cmd = AddCommand.create(domain, newContainer,
UMLPackage.Literals.PROFILE__METACLASS_REFERENCE, elementImport);
if (cmd.canExecute()) {
cmd.execute();
}
} else {
doTheDrop = false;
if (newProfile.getImportedMember(elementImport.getImportedElement().getName()) == null) {
newProfile.createMetaclassReference(elementImport.getImportedElement());
}
}
}
// Move the Element import and extension of a stereotype if the
// newContainer is a profile
if (semanticElement instanceof Stereotype) {
for (final Property property : ((Stereotype)semanticElement).getAttributes()) {
if (property.getName().startsWith("base_")) { //$NON-NLS-1$
Extension extension = null;
if (property.getAssociation() != null
&& property.getAssociation() instanceof Extension) {
extension = (Extension)property.getAssociation();
}
if (extension != null && ((Profile)oldContainer)
.getElementImport(extension.getMetaclass()) != null) {
final ElementImport elementImport = ((Profile)oldContainer)
.getElementImport(extension.getMetaclass());
dropFromDiagramProfileService(newContainer, extension, containerView);
if (elementImport != null) {
dropFromDiagramProfileService(newContainer, elementImport, containerView);
}
}
}
}
// Reset the current element as subject
cmd = AddCommand.create(domain, newContainer,
UMLPackage.Literals.PROFILE__METACLASS_REFERENCE, semanticElement);
if (cmd.canExecute()) {
cmd.execute();
}
}
}
if (doTheDrop) {
final ReusedDescriptionServices reusedDescriptionServices = new ReusedDescriptionServices();
reusedDescriptionServices.dropFromDiagram(newContainer, semanticElement, containerView);
}
}
/**
* Export profile.
*
* @param rootProfile
* Profile
*/
public void exportProfile(final Profile rootProfile) {
final Shell activeShell = PlatformUI.getWorkbench().getDisplay().getActiveShell();
final boolean isProfile = isProfileRoot(rootProfile);
if (isProfile && validateUmlElementWithProgress(rootProfile)) {
if (initParameters(rootProfile) == IDialogConstants.OK_ID
&& ProfileServices.INSTANCE.defineAllProfiles(rootProfile)) {
GenericUMLProfileTools.save(rootProfile);
final IProject profilePlugin = createPluginProjectWithProgress(profilePluginName);
// the following code is OK.
final IFolder modelFolder = profilePlugin.getFolder("model"); //$NON-NLS-1$
try {
modelFolder.create(false, true, null);
} catch (final CoreException e) {
LogServices.INSTANCE.error("exportProfile(" + rootProfile.getClass() //$NON-NLS-1$
+ ") not handled", e); //$NON-NLS-1$
}
// make a copy of the profile into the new plug-in used for the
// creation of static profile
final IFile profileCopyIFile = modelFolder.getFile(profileName + "." //$NON-NLS-1$
+ UMLResource.FILE_EXTENSION);
final IFile rootProfileIFile = GenericUMLProfileTools
.resourceToIFile(rootProfile.eResource());
try {
rootProfileIFile.copy(profileCopyIFile.getFullPath(), true, new NullProgressMonitor());
} catch (final CoreException e) {
LogServices.INSTANCE.error("exportProfile(" + rootProfile.getClass() //$NON-NLS-1$
+ ") not handled", e); //$NON-NLS-1$
}
final Resource profileCopyResource = new ResourceSetImpl()
.createResource(URI.createURI(profileCopyIFile.getFullPath().toString()));
final Profile profileCopy = (Profile)GenericUMLProfileTools
.load(profileCopyResource.getURI());
initEPackageStereotype(profileCopy);
final UmlToEcore umlToEcore = new UmlToEcore();
final Resource profileEcoreResource = umlToEcore.umlToEcore(profileCopy);
if (validateEObjectWithProgress(profileEcoreResource.getContents().get(0))) {
final EcoreToGenmodel ecoreToGenmodel = new EcoreToGenmodel();
final GenModel genModel = ecoreToGenmodel.ecoreToGenmodel(profileEcoreResource);
final GenerateModelCode generateModelCode = new GenerateModelCode();
generateModelCode.generateModelCode(genModel);
addProfileExtensions(profilePlugin, modelFolder, profileCopy);
// the following code is OK.
// IFolder targetBuild =
// profilePlugin.getFolder("targetBuild");
// try {
// targetBuild.create(false, true, null);
// } catch (CoreException e) {
// e.printStackTrace();
// }
try {
profilePlugin.build(IncrementalProjectBuilder.FULL_BUILD, new NullProgressMonitor());
} catch (final CoreException e) {
LogServices.INSTANCE.error(
"exportProfile(" //$NON-NLS-1$
+ rootProfile.getClass() + ") not handled", //$NON-NLS-1$
e);
}
final IWorkbenchWizard wizard = new PluginExportWizard();
final StructuredSelection selection = new StructuredSelection(profilePlugin);
wizard.init(PlatformUI.getWorkbench(), selection);
final WizardDialog wd = new ResizableWizardDialog(PDEPlugin.getActiveWorkbenchShell(),
wizard);
wd.create();
wd.open();
// Close the generated plugin, it contains uml.ecore and
// ecore.ecore that confused Acceleo in the VP.
try {
profilePlugin.close(new NullProgressMonitor());
} catch (final CoreException e) {
e.printStackTrace();
}
} else {
MessageDialog.openError(activeShell, "Exportation error", //$NON-NLS-1$
"Due to the error, the exportation will be stopped."); //$NON-NLS-1$
}
} else {
MessageDialog.openInformation(activeShell, "Exportation canceled", //$NON-NLS-1$
"Exportation canceled by user."); //$NON-NLS-1$
}
} else {
if (!isProfile) {
MessageDialog.openError(activeShell, "Exportation error", //$NON-NLS-1$
"The root element of this model is not a profile. Due to the error, the exportation will be stopped."); //$NON-NLS-1$
} else {
MessageDialog.openError(activeShell, "Exportation error", //$NON-NLS-1$
"Due to the error, the exportation will be stopped."); //$NON-NLS-1$
}
}
}
/**
* Iterate over the given {@link Collection} of root elements to find a {@link Type} element with the
* given name.
*
* @param roots
* the elements to inspect
* @param typeName
* the name to match
* @return the found {@link Type} or <code>null</code>
*/
public Type findTypeByName(Collection<EObject> roots, String typeName) {
return ElementServices.INSTANCE.findTypeByName(roots, typeName);
}
/**
* @see NodeInverseRefsServices#getAssociationInverseRefs(DDiagram)
*/
@SuppressWarnings("javadoc")
public Collection<EObject> getAssociationInverseRefs(DDiagram diagram) {
return NodeInverseRefsServices.INSTANCE.getAssociationInverseRefs(diagram);
}
/**
* Get all owned attributes of the classifier.
*
* @param classifier
* to find attribute from.
* @return a list of found attribute.
*/
public List<Property> getClassifierAttributes(final Classifier classifier) {
if (classifier instanceof Profile) {
return null;
}
final List<Property> properties = new ArrayList<Property>();
for (final Property property : classifier.getAttributes()) {
if (property.getAssociation() == null || !(property.getAssociation() instanceof Extension)) {
properties.add(property);
}
}
return properties;
}
/**
* Get all owned attributes of the classifier.
*
* @param classifier
* to find attribute from.
* @return a list of found attribute.
*/
public List<Property> getClassifierAttributes(final Profile classifier) {
return null;
}
/**
* Return the extension of an element import.
*
* @param extension
* source of element import
* @return The found element import.
*/
public ElementImport getElementImport(final Extension extension) {
return ExtensionServices.INSTANCE.getElementImport(extension);
}
/**
* Get the metaclass indicated by the association of the property 'property'.
*
* @param property
* the property
* @return the metaclass
*/
private Class getMetaclass(final Property property) {
Extension extension = null;
if (property.getAssociation() instanceof Extension) {
try {
extension = (Extension)property.getAssociation();
} catch (final Exception e) {
LogServices.INSTANCE.error("getMetaclass(" + property.getClass() + ") not handled", e); //$NON-NLS-1$ //$NON-NLS-2$
throw new RuntimeException(e);
}
}
return extension != null ? extension.getMetaclass() : null;
}
/**
* @see AssociationServices#getSource(Association)
*/
@SuppressWarnings("javadoc")
public Property getSource(Association association) {
return AssociationServices.INSTANCE.getSource(association);
}
/**
* Return the source of an Extra Association.
*
* @param stereotype
* the {@link Association} context
* @return first end of the Extra association
*/
public Stereotype getStereotypeSource(final Stereotype stereotype) {
if (stereotype.getAllAttributes() != null && stereotype.getAllAttributes().size() > 1) {
if (stereotype.getAllAttributes().get(1).getType() instanceof Stereotype) {
return (Stereotype)stereotype.getAllAttributes().get(1).getType();
}
}
return null;
}
/**
* Return the target of an Extra Association.
*
* @param stereotype
* the {@link Association} context
* @return second end of the Extra association
*/
public Stereotype getStereotypeTarget(final Stereotype stereotype) {
if (stereotype.getAllAttributes() != null && stereotype.getAllAttributes().size() > 2) {
if (stereotype.getAllAttributes().get(2).getType() instanceof Stereotype) {
return (Stereotype)stereotype.getAllAttributes().get(2).getType();
}
}
return null;
}
/**
* @see AssociationServices#getTarget(Association)
*/
@SuppressWarnings("javadoc")
public Property getTarget(Association association) {
return AssociationServices.INSTANCE.getTarget(association);
}
/**
* Find the imported metaclass to the profile.
*
* @param profile
* to test.
* @return a list of class.
*/
public List<PackageableElement> importMetaclass(final Profile profile) {
final List<PackageableElement> alreadyOnProfile = new ArrayList<PackageableElement>();
final List<String> alreadyOnProfileNames = new ArrayList<String>();
final ImportMetaclassDialog dialog = new ImportMetaclassDialog(
PlatformUI.getWorkbench().getDisplay().getActiveShell(), profile, true);
dialog.setHeaderMessageText("Select the UML Metaclasses to import."); //$NON-NLS-1$
dialog.open();
if (dialog.getResult() != null) {
final List<Object> selectedObjects = Arrays.asList(dialog.getResult());
for (final Object object : selectedObjects) {
if (object instanceof Class) {
final Class selectedMetaclass = (Class)object;
final PackageableElement importedMember = profile
.getImportedMember(selectedMetaclass.getName());
if (importedMember == null) {
profile.createMetaclassReference(selectedMetaclass);
} else {
// reserved for a future utilisation
alreadyOnProfile.add(importedMember);
alreadyOnProfileNames.add(importedMember.getName());
}
}
}
}
if (alreadyOnProfile.size() > 0) {
final String[] buttonList = {"Ok"}; //$NON-NLS-1$
final MessageDialog msgDialog = new MessageDialog(
PlatformUI.getWorkbench().getDisplay().getActiveShell(), "Already imported Metaclasses", //$NON-NLS-1$
null, "The following Metaclasses are already imported:" + "\n" //$NON-NLS-2$
+ alreadyOnProfileNames,
MessageDialog.INFORMATION, buttonList, 0);
msgDialog.open();
}
return alreadyOnProfile;
}
/**
* Apply the stereotype EPackage to the profile and fill out the tagged value.
*
* @param profile
* to initiate
*/
private void initEPackageStereotype(final Profile profile) {
final EList<Element> allOwningPackages = profile.allOwnedElements();
// allOwningPackages.add(profile);
final Profile ecoreProfile = (Profile)GenericUMLProfileTools
.load(URI.createURI("pathmap://UML_PROFILES/Ecore.profile.uml")); //$NON-NLS-1$
profile.applyProfile(ecoreProfile);
final Stereotype ePackage = ecoreProfile.getOwnedStereotype("EPackage"); //$NON-NLS-1$
profile.applyStereotype(ePackage);
if (profile.getName() != null) {
profile.setValue(ePackage, "packageName", profile.getName()); //$NON-NLS-1$
profile.setValue(ePackage, "nsPrefix", profile.getName()); //$NON-NLS-1$
profile.setValue(ePackage, "prefix", profile.getName()); //$NON-NLS-1$
}
// if (profile.getURI() != null && profile.getURI().length() != 0)
// profile.setValue(ePackage, nsURI, profile.getURI());
// else {
// profile.setValue(ePackage, nsURI, computeURI(profile));
// profile.setURI(computeURI(profile));
// }
profile.setValue(ePackage, NS_URI, rootProfileURI);
profile.setURI(rootProfileURI);
for (final Element ownedPackageElement : allOwningPackages) {
if (ownedPackageElement instanceof Package) {
final Package ownedPackage = (Package)ownedPackageElement;
ownedPackage.applyStereotype(ePackage);
if (ownedPackage.getName() != null) {
ownedPackage.setValue(ePackage, "packageName", //$NON-NLS-1$
ownedPackage.getName());
ownedPackage.setValue(ePackage, "nsPrefix", //$NON-NLS-1$
ownedPackage.getName());
ownedPackage.setValue(ePackage, "prefix", //$NON-NLS-1$
ownedPackage.getName());
}
if (ownedPackage.getURI() != null && profile.getURI().length() != 0) {
ownedPackage.setValue(ePackage, NS_URI, ownedPackage.getURI());
} else {
ownedPackage.setValue(ePackage, NS_URI, computeURI(ownedPackage));
ownedPackage.setURI(computeURI(ownedPackage));
}
}
}
GenericUMLProfileTools.save(profile);
}
/**
* Initiate the needed parameters for the export of the profile.
*
* @param profile
* to export.
* @return the pressed button, OK or CANCEL.
*/
private int initParameters(final Profile profile) {
if (profile.getName() != null && profile.getName().length() != 0) {
profileName = profile.getName().toLowerCase();
} else {
profileName = DEFAULT_PROFILE_NAME;
}
if (profile.getURI() != null && profile.getURI().length() != 0) {
rootProfileURI = profile.getURI() + SEPARATOR;
profilePluginName = rootProfileURI.replace("http://", "").replace( //$NON-NLS-1$ //$NON-NLS-2$
SEPARATOR, ".") //$NON-NLS-1$
+ "plugin"; //$NON-NLS-1$
} else {
rootProfileURI = OBEO_NETWORK_URI + profileName + SEPARATOR;
profilePluginName = OBEO_NETWORK_PLUGIN_NAME + "." + profileName + "." //$NON-NLS-1$ //$NON-NLS-2$
+ "plugin"; //$NON-NLS-1$
}
final InitProfilePluginDialog dialog = new InitProfilePluginDialog(profileName, rootProfileURI,
profilePluginName);
dialog.open();
if (dialog.getReturnCode() == IDialogConstants.OK_ID) {
profileName = dialog.getProfileName();
rootProfileURI = dialog.getRootProfileURI();
profilePluginName = dialog.getProfilePluginName();
return IDialogConstants.OK_ID;
}
return IDialogConstants.CANCEL_ID;
}
/**
* Verify if the model root is a Profile or not of a given profile.
*
* @param rootProfile
* the given profile
* @return true if the model root is a profile else false
*/
private boolean isProfileRoot(final Profile rootProfile) {
final EObject rootContainer = EcoreUtil.getRootContainer(rootProfile);
if (rootContainer != null && rootContainer instanceof Profile) {
return true;
}
return false;
}
/**
* Undefine the profile.
*
* @param rootProfile
* to undefine
*/
private void undefineProfile(final Profile rootProfile) {
if (rootProfile.getDefinition() != null) {
final List<Profile> allContentProfile = ProfileServices.INSTANCE.getAllSubProfiles(rootProfile);
rootProfile.getEAnnotations().remove(rootProfile.getDefinition().eContainer());
for (final Profile profile : allContentProfile) {
if (profile.getDefinition() != null) {
profile.getEAnnotations().remove(profile.getDefinition().eContainer());
}
}
}
}
/**
* Dialog message to undefine the profile.
*
* @param rootProfile
* to undefine
*/
public void undefineProfileDialog(final Profile rootProfile) {
final String[] buttonYesNo = {YES, NO};
final String[] buttonYes = {OK};
final Shell activeShell = PlatformUI.getWorkbench().getDisplay().getActiveShell();
MessageDialog msgDialogYesNo = null;
MessageDialog msgDialogYes = null;
if (rootProfile.getDefinition() != null) {
msgDialogYesNo = new MessageDialog(activeShell, UNDEFINE_PROFILE, null,
"Would you like to undefine this profile ?", MessageDialog.QUESTION, buttonYesNo, 1); //$NON-NLS-1$
final int diagResult = msgDialogYesNo.open();
if (diagResult == 0) {
undefineProfile(rootProfile);
msgDialogYes = new MessageDialog(activeShell, UNDEFINE_PROFILE, null,
"The profile is undefined", //$NON-NLS-1$
MessageDialog.INFORMATION, buttonYes, 0);
msgDialogYes.open();
}
} else {
msgDialogYes = new MessageDialog(activeShell, UNDEFINE_PROFILE, null,
"The profile is not defined !", //$NON-NLS-1$
MessageDialog.WARNING, buttonYes, 0);
msgDialogYes.open();
}
}
/**
* Validate an EObject using the emf validator.
*
* @param eObject
* the EObject
* @return true if no error or warning in the EObject otherwise return false.
*/
private boolean validateEObjectWithProgress(final EObject eObject) {
final ValidateEmfElement validateAction = new ValidateEmfElement();
final IStructuredSelection selection = new StructuredSelection(eObject);
validateAction.updateSelection(selection);
validateAction.setActiveWorkbenchPart(
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor());
validateAction.run();
return validateAction.getDiagnosticResult();
}
/**
* Validate an UML Element using the UML validator.
*
* @param element
* the EObject
* @return true if no error or warning in the EObject otherwise return false.
*/
private boolean validateUmlElementWithProgress(final Profile element) {
final ValidateUMLElement umlValidator = new ValidateUMLElement();
umlValidator.validateUMLmodel(element);
return umlValidator.getDiagnosticResult();
}
}